import { useState, useRef, useMemo, useCallback, useEffect } from 'react'
import { useRouter } from 'next/router'
import Image from 'next/image'
import Head from 'next/head'
import {
  Textarea,
  Input,
  Select,
  SelectItem,
  Button,
  Tooltip,
  Modal,
  ModalContent,
  ModalBody,
} from '@nextui-org/react'
import { Inter } from 'next/font/google'
import Title from '@/components/Title'
import Steps from '@/components/Steps'
import Intro from '@/components/Intro'
import Entries from '@/components/Entries'
import FAQ from '@/components/FAQ'
import Output from '@/components/Output'

import { useGlobalContext } from '@/contexts'
import initAssistantRequest from '@/shared/assistantRequest'
import { getPageData, getCreateParams, getSelectOptions } from '@/shared/utils'
import { AssistantProps } from '~/src/services'

import iconMagic from '@/assets/icons/ic_magic.png'
import runoutPC from '@/assets/runout-pc.png'
import runoutMobile from '@/assets/runout-mobile.png'

const inter = Inter({ subsets: ['latin'] })

const Generator = () => {
  const router = useRouter()
  const { pathname } = router
  const { insData } = useGlobalContext()
  const [keywords, setKeywords] = useState('')
  const [desc, setDesc] = useState('')
  const [style, setStyle] = useState('')
  const [locale, setLocale] = useState('')

  const [modalOpen, setModalOpen] = useState(false)
  const [isLoading, setIsLoading] = useState(false)
  const [errorTips, setErrorTips] = useState('')
  const [errorTipsOpen, setErrorTipsOpen] = useState(false)
  const [replyData, setReplyData] = useState('')
  const [historyList, setHistoryList] = useState<
    { timestamp: number; value: string }[]
  >([])

  const abortController = useRef<AbortController>()
  const textRef = useRef('')
  const timestampRef = useRef(0)

  const pageData = useMemo(
    () => getPageData(pathname, insData) as AssistantProps,
    [pathname, insData]
  )

  const lngs = useMemo(() => {
    const code = 'Language'
    return getSelectOptions(pageData, code)
  }, [pageData])

  useEffect(() => {
    if (!locale && lngs?.length) {
      setLocale(lngs[0].value)
    }
  }, [locale, lngs?.length])

  useEffect(() => {
    setTimeout(() => setErrorTipsOpen(false), 1000 * 5)
  }, [errorTips])

  const handleMessagesStream = useCallback((stream: string) => {
    if (!stream) return

    if (!textRef.current) {
      timestampRef.current = new Date().getTime()
    }

    textRef.current += stream.replace(/(\n|-=- --)/g, ' ')
    textRef.current = textRef.current.replace(/(\n|-=-n--)/g, '<br/>')

    setReplyData(textRef.current)
  }, [])

  const errorHandler = useCallback((type: string, failedType: string) => {
    // trackAssistant('error', { status: type, failedType })
    setErrorTips(failedType)
    setErrorTipsOpen(true)
  }, [])

  const handleOpenError = useCallback(
    (status: string) => {
      setIsLoading(false)

      const maps: { [key: string]: () => void } = {
        '202': () => {
          errorHandler('202', 'validate failed')
        },
        '241': () => {
          // credit run out
          // errorHandler('241', 'credit run out')
          setModalOpen(true)
        },
        '277': () => {
          errorHandler('277', 'request too much')
        },
        '278': () => {
          errorHandler('278', 'request frequency has reached the upper limit')
        },
        '279': () => errorHandler('279', 'forbidden words'),
        '280': () => {
          errorHandler(
            '280',
            'The input context exceeds 2000 characters, please cut it down and try again.'
          )
        },
        '401': () => {
          // free credit run out
          // errorHandler('401', 'free credit run out')
          setModalOpen(true)
        },
        '403': () => {
          // forbidden words
          errorHandler(
            '403',
            'There is a risk of violations, which may be due to factors such as violations and pornography'
          )
        },
        '429': () => {
          errorHandler('429', 'request frequency has reached the upper limit')
        },
      }
      if (maps[status]) {
        maps[status]()
        return
      } else {
        errorHandler(`${status}`, 'Server Error')
      }
    },
    [errorHandler]
  )

  const handleResetAnswerState = () => {
    textRef.current = ''
    timestampRef.current = 0
  }

  const handleMessageEnd = () => {
    setReplyData('')
    setHistoryList((prev) => [
      { timestamp: timestampRef.current, value: textRef.current },
      ...prev,
    ])
  }

  const handleGenerate = () => {
    if (!pageData) return
    const { assistantRequest, abortController: controller } =
      initAssistantRequest()

    abortController.current = controller

    setIsLoading(true)

    const createPrams = getCreateParams(pageData, [
      keywords,
      desc,
      style,
      locale,
    ])
    console.log('createPrams >>>>', createPrams)

    assistantRequest({
      data: createPrams,
      language: 'en',
      onOpenSuccess(response: any) {
        console.log('onOpenSuccess event >>>', response)
        handleResetAnswerState()
        if (response.status !== 200) {
          handleOpenError(response.status)
        }
      },
      onOpenError: (response: any) => {
        console.log('onOpenError event >>>', response)
        handleOpenError(response.status)
      },
      onMessage: (event: any) => {
        handleMessagesStream(event?.data)
      },
      onMessageEnd: () => {
        console.log('onMessageEnd event >>>')
        handleMessageEnd()
        // handleMessageStreamEnd()
      },
      onClose: () => {
        console.log('onClose event >>>')
        setIsLoading(false)
      },
      onError: (event: any) => {
        console.log('onError event >>>', event)
        setIsLoading(false)
      },
    }).catch((err) => {
      console.log('assistantRequest err >>>>', err)
    })
  }

  return (
    <>
      <div className="flex flex-col gap-y-4 w-[840px] min-h-[316px] px-3.5 py-6 bg-white mx-[auto] mb-row shadow-lg max-sm:w-full max-sm:mb-0 rounded-[20px]">
        <div className="flex flex-col gap-y-2">
          <div className="flex flex-row items-center justify-between">
            <span className="text-base font-bold">Short Description *</span>
            <span className="text-sm text-secondary">
              {keywords.length}/200
            </span>
          </div>
          <Textarea
            variant="bordered"
            placeholder="What is the post about?"
            value={keywords}
            onValueChange={(val) => {
              setKeywords(val.slice(0, 200))
            }}
          />
        </div>
        <div className="flex flex-col gap-y-2">
          <div className="flex flex-row items-center justify-between">
            <span className="text-base font-bold">Keywords</span>
            <span className="text-sm text-secondary">{desc.length}/100</span>
          </div>
          <Input
            variant="bordered"
            placeholder="Any keywords you want included in the caption"
            value={desc}
            onValueChange={(val) => {
              setDesc(val.slice(0, 100))
            }}
          />
        </div>
        <div className="flex flex-row justify-between gap-x-8 max-sm:flex-col max-sm:gap-y-4">
          <div className="flex-1 flex flex-col gap-y-2">
            <div className="flex flex-row items-center justify-between">
              <span className="text-base font-bold">Style</span>
              <span className="text-sm text-secondary">{desc.length}/100</span>
            </div>
            <Input
              variant="bordered"
              placeholder="Specify writing style, e.g., inspirational, formal"
              value={style}
              onValueChange={(val) => {
                setStyle(val.slice(0, 100))
              }}
            />
          </div>
          <div className="flex-1 flex flex-col gap-y-2">
            <div className="flex flex-row items-center justify-between">
              <span className="text-base font-bold">Language</span>
            </div>
            {lngs && (
              <Select
                aria-label="select language"
                variant="bordered"
                selectionMode="single"
                items={lngs}
                selectedKeys={[locale]}
                defaultSelectedKeys={[locale]}
                onSelectionChange={(val: any) => {
                  setLocale(val.currentKey)
                }}
              >
                {lngs.map((lng) => (
                  <SelectItem key={lng.value} value={lng.value}>
                    {lng.label}
                  </SelectItem>
                ))}
              </Select>
            )}
          </div>
        </div>
        <Tooltip
          color={'danger'}
          isOpen={errorTipsOpen}
          showArrow
          isDismissable
          placement="bottom"
          content={errorTips}
        >
          <Button
            className="flex w-full button-primary cursor-pointer"
            isDisabled={!keywords.length || isLoading}
            isLoading={isLoading}
            onClick={handleGenerate}
          >
            <Image src={iconMagic} alt="icon" width={22} height={22} />
            Generate
          </Button>
        </Tooltip>
        <div className="flex flex-col gap-4 max-sm:hidden">
          {[
            { timestamp: timestampRef.current, value: replyData },
            ...historyList,
          ].map((item, index) => (
            <Output
              key={`${item.timestamp}-${index}`}
              timeStamp={new Date().getTime()}
              content={item.value}
              // onCopy={() => {}}
              onDelete={() => setHistoryList((prev) => prev.splice(index, 1))}
            />
          ))}
        </div>
      </div>
      <div className="flex flex-col gap-6 pt-6 lg:hidden">
        {[
          { timestamp: timestampRef.current, value: replyData },
          ...historyList,
        ].map((item, index) => (
          <Output
            key={`${item.timestamp}-${index}`}
            timeStamp={new Date().getTime()}
            content={item.value}
            // onCopy={() => {}}
            onDelete={() => setHistoryList((prev) => prev.splice(index, 1))}
          />
        ))}
      </div>
      <Modal
        isOpen={modalOpen}
        placement="center"
        onClose={() => setModalOpen(false)}
      >
        <ModalContent>
          <ModalBody className="p-0">
            <Image
              className="max-sm:hidden"
              src={runoutPC}
              alt="run out picture"
              width={819}
              height={662}
            ></Image>
            <Image
              className="sm:hidden"
              src={runoutMobile}
              alt="run out picture"
              width={640}
              height={872}
            ></Image>
          </ModalBody>
        </ModalContent>
      </Modal>
    </>
  )
}

export default function Home() {
  const StepsData = {
    title: 'Instagram Caption Generator: A Simple Guide',
    desc: `The Instagram caption generator is an AI tool designed to help you create creative and engaging captions for your Instagram posts. Using this tool is very simple.`,
    steps: [
      {
        step: 'Step 1',
        title: 'Enter a description',
        desc: 'In the input box of the Caption Generator, tell AI what your post is about, and what keywords or call-to-actions you want to include. The more information you provide, the more relevant the AI-generated captions will be.',
        img: require('@/assets/caption/step-1.png').default,
      },
      {
        step: 'Step 2',
        title: 'Choose tone and language',
        desc: `Select a tone that matches your Instagram account best. You can also try different tones to see which one works best.`,
        img: require('@/assets/caption/step-2.png').default,
      },
      {
        step: 'Step 3',
        title: 'Generate AI captions for Instagram',
        desc: `Click the 'Generate' button, and the AI will instantly produce three different caption options for you to choose from. It will also suggest relevant hashtags and emojis. Select the captions you prefer, and then post it on Instagram.`,
        img: require('@/assets/caption/step-3.png').default,
      },
    ],
  }
  const IntroData = {
    title: 'Why Use AI Caption Generator for Instagram? ',
    desc: [
      `If you're looking to craft engaging captions quickly and easily, don't miss our Instagram Caption Generator. This tool not only simplifies your copywriting process but also assists in generating hashtags and keywords to increase the performance of your Instagram posts. `,
      `Whether you're an individual, marketer, or social media influencer, our Instagram caption generator works for you. Simply provide a brief description and keywords,  choose your desired tone,  AI will start working and generate creative captions for your Instagram post in a few seconds,  This will reduce your brainstorming time significantly and save you effort.`,
    ],
    intros: [
      {
        title: 'Efficient caption generation',
        desc: `The biggest advantage of using AI to generate Instagram captions is that it saves you time. Instead of thinking hard about how to make a good caption on Instagram, you can use AI to quickly generate multiple caption options, and select the one that best fits your personal style or brand tone.`,
        img: require('@/assets/caption/icon-fast.png'),
      },
      {
        title: 'Continuously updated',
        desc: `Our Instagram caption generator does more than just get the job done. It stays informed about what Instagram users like and the current trends, so it will generate captions carefully to ensure your post get more likes, comments, and shares.`,
        img: require('@/assets/caption/icon-update.png'),
      },
      {
        title: '100% free to use',
        desc: `Unlike many other AI caption generators that eventually require a subscription, our tool is completely free. We developed it to help Instagram users improve social media performance, so we don’t charge for the task. In fact, all Instagram tools on the SSSgram website are free—don’t forget to share with your friends and bookmark our site. `,
        img: require('@/assets/caption/icon-cash.png'),
      },
    ],
  }
  const EntriesData = {
    title: 'Can this AI tool generate captions from photo? ',
    entries: [
      {
        label: 'Instagram Hashtag Generator',
        link: '/instagram-hashtag-generator/',
      },
      {
        label: 'Instagram Username Generator',
        link: '/instagram-username-generator/',
      },
      { label: 'Instagram Bio Generator', link: '/instagram-bio-generator/' },
    ],
  }
  const FAQData = {
    title: 'FAQs',
    faqs: [
      {
        question: 'How long can an Instagram caption be?',
        answer: `Instagram has a caption length limit of 2,200 characters per post. However, it is not recommended to include too much information in the caption, it is better to keep it concise and use line breaks to separate different thoughts. This will ensure your subtitles are easy to read and effectively capture your audience's attention.`,
      },
      {
        question: 'Should I include an emoji in the caption?',
        answer:
          'Adding emojis to your Instagram captions is a good practice to increase engagement and clearly communicate emotions, making your posts more visually appealing and relatable. But be careful not to use too much emojis.',
      },
      {
        question: 'Can I use this caption generator on other social media?',
        answer:
          'Yes, the Caption feature is similar on various social media, so you can use the Instagram caption generator on other social media platforms like Facebook and TikTok. Note, however, you should consider the style differences and character limits specific to each platform.',
      },
    ],
  }
  return (
    <main
      className={`w-view min-h-screen mx-[auto] ${inter.className} max-sm:w-sView max-sm:px-[10px]`}
    >
      <Head>
        <title>Free AI Instagram Caption Generator (Free Tool)</title>
        <meta
          name="description"
          content="You can use AI to generate captions for Instagram and other social media to improve likes and follows. The tool is 100% free to use. "
        />
        <meta
          property="og:title"
          content="Free AI Instagram Caption Generator (Free Tool)"
        />
        <meta
          property="og:description"
          content="You can use AI to generate captions for Instagram and other social media to improve likes and follows. The tool is 100% free to use. "
        />
      </Head>
      <Title
        title="Free AI Instagram Caption Generator"
        desc="Craft engaging Instagram captions in seconds with our AI-powered caption generator."
      ></Title>
      <Generator />
      <Intro {...IntroData} />
      <Steps {...StepsData} />
      <FAQ {...FAQData} />
      <Entries {...EntriesData} />
    </main>
  )
}
